package com.ibuonline.search.solr.score;

import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.greenpineyu.fel.Expression;
import com.greenpineyu.fel.FelEngine;
import com.greenpineyu.fel.FelEngineImpl;
import com.greenpineyu.fel.context.FelContext;
import com.greenpineyu.fel.context.MapContext;
import com.ibuonline.utils.ExpressionUtils;

public class ScoreExpression {
	private static Logger log = LoggerFactory
			.getLogger(ExpressionXscorerFactory.class);

	private String expressionString;// 表达式
	private Expression expression;// 表达式对象
	private List<String> propNames;// 表达式变量

	public ScoreExpression(String expressionString) {
		this.expressionString = expressionString;
		this.propNames = ExpressionUtils.getVars(expressionString);
		FelEngine felEngine = new FelEngineImpl();
		this.expression = felEngine.compile(expressionString,
				getDefaultValues());
	}

	public float eval(Map<String, Object> data) {
		FelContext env = getDefaultValues();
		if (data != null) {
			for (Map.Entry<String, Object> entry : data.entrySet()) {
				env.set(entry.getKey(), entry.getValue());
			}
			try {
				Object result = expression.eval(env);
				if (result instanceof Double) {
					return ((Double) result).floatValue();
				} else if (result instanceof Integer) {
					return ((Integer) result).floatValue();
				} else {
					return (Float) result;
				}
			} catch (RuntimeException e) {
				log.error("run score() method error.", e);
				return 0f;
			}
		}
		return 0f;
	}

	/**
	 * @return the expressionString
	 */
	public String getExpressionString() {
		return expressionString;
	}

	/**
	 * @return the expression
	 */
	public Expression getExpression() {
		return expression;
	}

	/**
	 * @return the propNames
	 */
	public List<String> getPropNames() {
		return propNames;
	}

	public FelContext getDefaultValues() {
		FelContext ctx = new MapContext();
		for (String property : propNames) {
			ctx.set(property, 0f);
		}
		return ctx;
	}
}
